package com.fimmlps.reronge.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fimmlps.reronge.dto.*;
import com.fimmlps.reronge.entity.*;
import com.fimmlps.reronge.service.*;
import com.fimmlps.reronge.vo.TResponseVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.logging.Logger;

@RestController
@RequestMapping("/entrySingle")
public class EntrySingleController {
    @Autowired
    private IEntrySingleService singleService;

    @Autowired
    private IEntryTriggerService triggerService;

    @Autowired
    private IEntryUsageService usageService;

    @Autowired
    private IEntryCommentService commentService;

    @Autowired
    private IEntryUserService userService;

    @Autowired
    private IEntryCollectService collectService;

    //大致要实现以下功能：
    //1.根据trigger名查找
    //2.根据词条名查找
    //3.按最新顺序，返回某一页的所有词条
    //5.按热度顺序，返回某一页的所有词条 （热度解释：词条点击量）

    public List<EntrySinglePreviewDto> spawnSinglePreviewDtoList(List<EntrySingle> totals){
        List<EntrySinglePreviewDto> dtoList = new ArrayList<>();
        for(int i = 0;i<totals.size();i++){
            EntrySinglePreviewDto dto = new EntrySinglePreviewDto(totals.get(i));
            List<EntryTrigger> triggers = triggerService.getEnabledTriggersBySingleId((int) dto.getEntrySingleId());
            List<EntryTriggerDto> triggerDtoList = EntryTriggerDto.toDtoList(triggers);
            dto.setTriggers(triggerDtoList);
            dtoList.add(dto);
        }
        return dtoList;
    }

    public List<EntrySinglePreviewDto> spawnSinglePreviewDtoListFromMatchIDs(ArrayList<Integer> entryIDs){
        if(entryIDs.size()==0)
            return new ArrayList<>();
        List<EntrySingle> singles;
        Set<Integer> singleIDs = new HashSet<>(entryIDs);
        singles = singleService.listByIds(singleIDs);
        List<EntrySinglePreviewDto> espDtos = new ArrayList<>();
        for(EntrySingle es:singles)
            espDtos.add(new EntrySinglePreviewDto(es));
        return espDtos;
    }

    public List<EntrySinglePreviewDto> spawnSinglePreviewDtoListByTriggers(List<EntryTrigger> triggers){
        if(triggers.size() ==0)
            return new ArrayList<>();
        List<EntrySingle> singles;
        Set<Integer> singleIDs = new HashSet<>();
        for(EntryTrigger trigger:triggers){
            singleIDs.add(trigger.getEntrySingleId());
        }
        singles = singleService.listByIds(singleIDs);
        List<EntrySinglePreviewDto> espDtos = new ArrayList<>();
        for(EntrySingle es:singles)
            espDtos.add(new EntrySinglePreviewDto(es));
        return espDtos;
    }

    public List<EntryCommentDto> spawnCommentDtoList(List<EntryComment> commentList){
        HashMap<Integer,EntryCommentDto> baseMap = new HashMap<>();
        List<EntryCommentDto> cdtoList = new ArrayList<>();
        List<EntryCommentDto> replyLists = new ArrayList<>();
        for(EntryComment comment:commentList){
            EntryCommentDto cdto = new EntryCommentDto(comment);
            EntryUser user = userService.getById(comment.getUserId());
            if(user!=null){
                cdto.setUserName(user.getUserName());
                cdto.setUserHeadUrl(user.getUserHeadUrl());
            }
            if(cdto.getEntryCommentTopId()!=null&&cdto.getEntryCommentTopId()>0){
                replyLists.add(cdto);
            }
            else {
                cdtoList.add(cdto);
                baseMap.put(cdto.getEntryCommentId(),cdto);
            }
        }
        //添加reply
        for(EntryCommentDto dto:replyLists){
            EntryCommentDto baseDto = baseMap.get(dto.getEntryCommentTopId());
            if(baseDto!=null){
                baseDto.getReplyList().add(dto);
            }
        }
        return cdtoList;
    }

    //GET 随机返回5条数据
    @GetMapping("/getRandomContents")
    public TResponseVo<List<EntrySinglePreviewDto>> getRandomContents(){
        try {
            List<EntrySingle> totals = singleService.list();
            Logger.getGlobal().info("条目数："+totals.size());
            Collections.shuffle(totals);
            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(dtoList);

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 获取tags
    //参数 tags
    @PostMapping("/getEntrySinglesByTags")
    public TResponseVo<PreviewSingleDto> getEntrySinglesByTags(@RequestBody Map<String, Object> map){
        try {
            ArrayList<String> tagList = (ArrayList<String>) map.get("tags");
            List<EntryTrigger> triggers = triggerService.getTriggersFromText(tagList);
            List<EntrySinglePreviewDto> espDtos = spawnSinglePreviewDtoListByTriggers(triggers);
            return TResponseVo.success(new PreviewSingleDto(espDtos));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 获取热词解析结果
    //REMAKE 2024/04/07
    @PostMapping("/getEntryTips")
    public TResponseVo<PreviewSingleDto> getEntryTips(@RequestBody MatchKeywordsDto matchKeywordsDto){
        try {
            ArrayList<Integer> ids = new ArrayList<>(matchKeywordsDto.getMatched_entryIds());
            ids.addAll(matchKeywordsDto.getMatched_usage_entryIds());
            List<EntrySinglePreviewDto> espDtos = spawnSinglePreviewDtoListFromMatchIDs(ids);
            return TResponseVo.success(new PreviewSingleDto(espDtos));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 获取最近一个月最热门的N个梗
    //参数： pageIndex （页面号，从1开始） pageSize（页面大小）
    @PostMapping("/getRecentHottestContentsByPage")
    public TResponseVo<PageSingleDto> getRecentHottestContentsByPage(@RequestBody Map<String, Object> map){
        try {
            int index = (int) map.get("pageIndex");
            int pageSize = (int) map.get("pageSize");
            Logger.getGlobal().info("页面信息，页号："+index + "；页面大小："+pageSize);

            QueryWrapper<EntrySingle> newest = new QueryWrapper<>();
            LocalDateTime oneMonthAgo = LocalDateTime.now().minusMonths(1);
            newest.ge("update_time",oneMonthAgo);
            newest.orderByDesc("clicks").orderByDesc("update_time");
            Page<EntrySingle> page = new Page<>(index,pageSize);
            IPage<EntrySingle> iPage = singleService.page(page,newest);
            List<EntrySingle> totals = iPage.getRecords();

            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(new PageSingleDto(index,dtoList.size(),dtoList));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 按最新更新时间顺序分页获取
    //参数： pageIndex （页面号，从1开始） pageSize（页面大小）
    @PostMapping("/getNewestContentsByPage")
    public TResponseVo<PageSingleDto> getNewestContentsByPage(@RequestBody Map<String, Object> map){
        try {
            int index = (int) map.get("pageIndex");
            int pageSize = (int) map.get("pageSize");
            Logger.getGlobal().info("页面信息，页号："+index + "；页面大小："+pageSize);

            QueryWrapper<EntrySingle> newest = new QueryWrapper<>();
            newest.orderByDesc("update_time");
            Page<EntrySingle> page = new Page<>(index,pageSize);
            IPage<EntrySingle> iPage = singleService.page(page,newest);
            List<EntrySingle> totals = iPage.getRecords();

            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(new PageSingleDto(index,dtoList.size(),dtoList));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 按最多点击顺序分页获取
    //参数： pageIndex （页面号，从1开始） pageSize（页面大小）
    @PostMapping("/getHottestContentsByPage")
    public TResponseVo<PageSingleDto> getHottestContentsByPage(@RequestBody Map<String, Object> map){
        try {
            int index = (int) map.get("pageIndex");
            int pageSize = (int) map.get("pageSize");
            Logger.getGlobal().info("页面信息，页号："+index + "；页面大小："+pageSize);

            QueryWrapper<EntrySingle> hottest = new QueryWrapper<>();
            hottest.orderByDesc("clicks");
            Page<EntrySingle> page = new Page<>(index,pageSize);
            IPage<EntrySingle> iPage = singleService.page(page,hottest);
            List<EntrySingle> totals = iPage.getRecords();

            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(new PageSingleDto(index,dtoList.size(),dtoList));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 搜索（区别是搜索框是否有内容等trigger） 按最新排序
    //参数： pageIndex （页面号，从1开始） pageSize（页面大小） content
    @PostMapping("/searchNewestContentsByPage")
    public TResponseVo<PageSingleDto> searchNewestContentsByPage(@RequestBody Map<String, Object> map){
        try {
            String content = (String) map.get("content");
            int index = (int) map.get("pageIndex");
            int pageSize = (int) map.get("pageSize");
            Logger.getGlobal().info("页面信息，页号："+index + "；页面大小："+pageSize+"；搜索内容："+content);
            QueryWrapper<EntrySingle> newest = new QueryWrapper<>();
            newest.like("title",content).or().like("resume",content).or().like("description",content);
            newest.orderByDesc("update_time");
            Page<EntrySingle> page = new Page<>(index,pageSize);
            IPage<EntrySingle> iPage = singleService.page(page,newest);
            List<EntrySingle> totals = iPage.getRecords();

            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(new PageSingleDto(index,dtoList.size(),dtoList));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 搜索（区别是搜索框是否有内容等trigger） 按最热门排序
    //参数： pageIndex （页面号，从1开始） pageSize（页面大小） content
    @PostMapping("/searchHottestContentsByPage")
    public TResponseVo<PageSingleDto> searchHottestContentsByPage(@RequestBody Map<String, Object> map){
        try {
            String content = (String) map.get("content");
            int index = (int) map.get("pageIndex");
            int pageSize = (int) map.get("pageSize");
            Logger.getGlobal().info("页面信息，页号："+index + "；页面大小："+pageSize+"；搜索内容："+content);

            QueryWrapper<EntrySingle> hottest = new QueryWrapper<>();
            hottest.like("title",content).or().like("resume",content).or().like("description",content);
            hottest.orderByDesc("clicks");
            Page<EntrySingle> page = new Page<>(index,pageSize);
            IPage<EntrySingle> iPage = singleService.page(page,hottest);
            List<EntrySingle> totals = iPage.getRecords();

            List<EntrySinglePreviewDto> dtoList = spawnSinglePreviewDtoList(totals);
            return TResponseVo.success(new PageSingleDto(index,dtoList.size(),dtoList));

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    // *IMPORTANT
    //POST 根据词条ID进入词条页面，获取完整信息 包括本体、评论等 会触发clicks++的效果
    //参数 entrySingleId
    @PostMapping("/getEntrySingleById")
    public TResponseVo<EntrySingleDto> getEntrySingleById(@RequestBody Map<String,Object> map){
        try {
            int id = (int) map.get("entrySingleId");
            EntrySingle single = singleService.getById(id);
            if(single!=null){
                //clicks++
                single.setClicks(single.getClicks()+1);
                singleService.updateById(single);
                EntrySingleDto dto = new EntrySingleDto(single);
                List<EntryTrigger> triggers = triggerService.getEnabledTriggersBySingleId((int) dto.getEntrySingleId());
                List<EntryTriggerDto> triggerDtoList = EntryTriggerDto.toDtoList(triggers);
                dto.setTriggers(triggerDtoList);
                List<EntryComment> commentList = commentService.list(new QueryWrapper<EntryComment>().eq("entry_single_id",id));
                if(commentList!=null){
                    dto.setComments(spawnCommentDtoList(commentList));
                }
                //update 2025/4/15
                List<EntryUsage> usages = usageService.getEnabledUsagesBySingleId((int) dto.getEntrySingleId());
                List<EntryUsageDto> usageDtoList = EntryUsageDto.toDtoList(usages);
                dto.setUsages(usageDtoList);

                if(single.getCreateUserId()!=null){
                    EntryUser creator = userService.getById(single.getCreateUserId());
                    if(creator!=null){
                        dto.setCreatorId(creator.getUserId());
                        dto.setCreator(creator.getUserName());
                    }
                }

                return TResponseVo.success(dto);
            }
            else {
                return TResponseVo.error(404,"没有获取到entrySingle");
            }

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    // *IMPORTANT -2
    //POST （登录状态下）根据词条ID进入词条页面，获取完整信息 包括本体、评论等 会触发clicks++的效果 以返回是否已收藏的信息
    //参数 userName entrySingleId
    @PostMapping("/getEntrySingleByIdLogged")
    public TResponseVo<EntrySingleDto> getEntrySingleByIdLogged(@RequestBody Map<String,Object> map){
        try {
            String userName = (String) map.get("userName");
            int id = (int) map.get("entrySingleId");
            EntryUser user = userService.getOne(new QueryWrapper<EntryUser>().eq("user_name",userName));
            if(user==null){
                return TResponseVo.error(400,"没有该用户！");
            }
            EntrySingle single = singleService.getById(id);
            if(single!=null){
                //clicks++
                single.setClicks(single.getClicks()+1);
                singleService.updateById(single);
                EntrySingleDto dto = new EntrySingleDto(single);
                List<EntryTrigger> triggers = triggerService.getEnabledTriggersBySingleId((int) dto.getEntrySingleId());
                List<EntryTriggerDto> triggerDtoList = EntryTriggerDto.toDtoList(triggers);
                dto.setTriggers(triggerDtoList);
                List<EntryComment> commentList = commentService.list(new QueryWrapper<EntryComment>().eq("entry_single_id",id));
                if(commentList!=null){
                    dto.setComments(spawnCommentDtoList(commentList));
                }
                //update 2025/4/15
                List<EntryUsage> usages = usageService.getEnabledUsagesBySingleId((int) dto.getEntrySingleId());
                List<EntryUsageDto> usageDtoList = EntryUsageDto.toDtoList(usages);
                dto.setUsages(usageDtoList);

                //update 2025/4/29
                EntryCollect collect = collectService.getCollect(user.getUserId(),single.getEntrySingleId());
                dto.setCollected(collect!=null);

                if(single.getCreateUserId()!=null){
                    EntryUser creator = userService.getById(single.getCreateUserId());
                    if(creator!=null){
                        dto.setCreatorId(creator.getUserId());
                        dto.setCreator(creator.getUserName());
                    }
                }

                return TResponseVo.success(dto);
            }
            else {
                return TResponseVo.error(404,"没有获取到entrySingle");
            }

        }catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 写entry
    //参数 EntryWriteDto （此间entrySingleId不需用到）
    @PostMapping("/writeEntry")
    public TResponseVo<EntrySingleDto> writeEntry(@RequestBody EntryWriteDto write){
        try {
            String writer = write.getUserName();
            EntryUser user = userService.getUserByName(writer);
            if(user==null){
                return TResponseVo.error(500,"用户不存在！");
            }
            EntrySingle single = new EntrySingle();
            single.setTitle(write.getTitle());
            single.setResume(write.getResume());
            single.setDescription(write.getDescription());
            single.setHtmlContent(write.getHtmlContent());
            single.setCreateTime(LocalDateTime.now());
            single.setUpdateTime(LocalDateTime.now());
            single.setClicks(0);
            single.setCreateUserId(user.getUserId());
            singleService.save(single);

            ArrayList<String> tags = write.getTriggers();
            if(!tags.contains(single.getTitle())){
                tags.add(0,single.getTitle());
            }
            ArrayList<EntryTrigger> triggers = new ArrayList<>();
            for(String s:tags){
                EntryTrigger trigger = new EntryTrigger();
                trigger.setEntrySingleId(single.getEntrySingleId());
                trigger.setText(s);
                trigger.setEnabled(0);
                triggerService.save(trigger);
                triggers.add(trigger);
            }
            //update 2025/4/15
            ArrayList<String> uss = write.getUsages();
            ArrayList<EntryUsage> usages = new ArrayList<>();
            for(String s:uss){
                EntryUsage usage = new EntryUsage();
                usage.setEntrySingleId(single.getEntrySingleId());
                usage.setText(s);
                usage.setEnabled(0);
                usageService.save(usage);
                usages.add(usage);
            }

            EntrySingleDto dto = new EntrySingleDto(single);
            dto.setTriggers(EntryTriggerDto.toDtoList(triggers));
            dto.setUsages(EntryUsageDto.toDtoList(usages));
            return TResponseVo.success(dto);
        }
        catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 编辑entry
    //参数 EntryWriteDto
    //注：与写entry不同的是，需要传入entrySingleId，且会调整所有triggers
    @PostMapping("/updateEntry")
    public TResponseVo<EntrySingleDto> updateEntry(@RequestBody EntryWriteDto write){
        try {
            String writer = write.getUserName();
            EntryUser user = userService.getUserByName(writer);
            if(user==null){
                return TResponseVo.error(500,"用户不存在！");
            }
            EntrySingle single = singleService.getById(write.getEntrySingleId());
            if(single==null){
                return TResponseVo.error(500,"词条不存在！");
            }
            single.setTitle(write.getTitle());
            single.setResume(write.getResume());
            single.setDescription(write.getDescription());
            single.setHtmlContent(write.getHtmlContent());
            single.setUpdateTime(LocalDateTime.now());
            singleService.updateById(single);

            ArrayList<String> tags = write.getTriggers();
            if(!tags.contains(single.getTitle())){
                tags.add(0,single.getTitle());
            }
            ArrayList<EntryTrigger> triggers = triggerService.getEnabledTriggersBySingleId(single.getEntrySingleId());
            for(EntryTrigger trigger:triggers){
                if(!tags.contains(trigger.getText())){
                    trigger.setEnabled(1);
                    triggerService.updateById(trigger);
                }
                else{
                    tags.remove(trigger.getText());
                }
            }
            //add tags
            for(String s:tags){
                EntryTrigger trigger = new EntryTrigger();
                trigger.setEntrySingleId(single.getEntrySingleId());
                trigger.setText(s);
                trigger.setEnabled(0);
                triggerService.save(trigger);
                triggers.add(trigger);
            }
            //update 2025/4/15
            ArrayList<String> uss = write.getUsages();
            ArrayList<EntryUsage> usages = usageService.getEnabledUsagesBySingleId(single.getEntrySingleId());
            for(EntryUsage usage:usages){
                if(!uss.contains(usage.getText())){
                    usage.setEnabled(1);
                    usageService.updateById(usage);
                }
                else{
                    uss.remove(usage.getText());
                }
            }
            //add uss
            for(String s:uss){
                EntryUsage usage = new EntryUsage();
                usage.setEntrySingleId(single.getEntrySingleId());
                usage.setText(s);
                usage.setEnabled(0);
                usageService.save(usage);
                usages.add(usage);
            }

            EntrySingleDto dto = new EntrySingleDto(single);
            dto.setTriggers(EntryTriggerDto.toDtoList(triggers));
            dto.setUsages(EntryUsageDto.toDtoList(usages));

            return TResponseVo.success(dto);
        }
        catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 评论
    //参数 用户名-userName 词条id-entrySingleId 根评论id-entryCommentTopId 内容-text
    @PostMapping("/writeComment")
    public TResponseVo<EntryCommentDto> writeComment(@RequestBody Map<String,Object> map){
        try {
            String userName = (String) map.get("userName");
            int entrySingleId = (int)map.get("entrySingleId");
            int entryCommentTopId = (int)map.get("entryCommentTopId");
            String text = (String) map.get("text");
            EntryUser user = userService.getOne(new QueryWrapper<EntryUser>().eq("user_name",userName));
            if(user==null){
                return TResponseVo.error(400,"没有该用户！");
            }
            int userId = user.getUserId();
            EntryComment cmt = new EntryComment();
            cmt.setUserId(userId);
            cmt.setEntrySingleId(entrySingleId);
            cmt.setEntryCommentTopId(entryCommentTopId);
            cmt.setText(text);
            cmt.setCreateTime(LocalDateTime.now());
            commentService.save(cmt);
            EntryCommentDto dto = new EntryCommentDto(cmt);
            dto.setUserName(user.getUserName());
            dto.setUserHeadUrl(user.getUserHeadUrl());
            return new TResponseVo<>(200,dto,"评论/回复成功");

        } catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }

    }

    //POST 收藏 或 取消收藏
    //参数 用户名-userName 词条id-entrySingleId
    @PostMapping("/collect")
    public TResponseVo<String> collect(@RequestBody Map<String,Object> map){
        try {
            String userName = (String) map.get("userName");
            int entrySingleId = (int)map.get("entrySingleId");
            EntryUser user = userService.getOne(new QueryWrapper<EntryUser>().eq("user_name",userName));
            if(user==null){
                return TResponseVo.error(400,"没有该用户！");
            }
            EntrySingle single = singleService.getById(entrySingleId);
            if(single==null){
                return TResponseVo.error(400,"词条不存在！");
            }
            EntryCollect collect = collectService.getCollect(user.getUserId(),single.getEntrySingleId());
            if(collect==null){
                collect = new EntryCollect();
                collect.setUserId(user.getUserId());
                collect.setEntrySingleId(single.getEntrySingleId());
                collect.setEntrySingleTitle(single.getTitle());
                collect.setEntrySingleResume(single.getResume());
                collect.setCollectFolderTitle("默认收藏夹");
                collect.setCreateTime(LocalDateTime.now());
                collectService.save(collect);
                return TResponseVo.success("收藏成功");
            }
            else{
                collectService.removeById(collect);
                return TResponseVo.success("取消收藏成功");
            }
        }
        catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }

    //POST 获取所有收藏的词条
    //参数 用户名-userName
    @PostMapping("/getAllCollect")
    public TResponseVo<TotalCollectDto> getAllCollect(@RequestBody Map<String, Object> map){
        try {
            String userName = (String) map.get("userName");
            EntryUser user = userService.getOne(new QueryWrapper<EntryUser>().eq("user_name",userName));
            if(user==null){
                return TResponseVo.error(400,"没有该用户！");
            }
            QueryWrapper<EntryCollect> collectQW = new QueryWrapper<>();
            collectQW.eq("user_id",user.getUserId()).orderByDesc("create_time");
            List<EntryCollect> collectList = collectService.list(collectQW);
            TotalCollectDto collectDto = new TotalCollectDto();
            collectDto.setUserName(userName);
            collectDto.setCollects(new ArrayList<>(collectList));
            return TResponseVo.success(collectDto);
        }
        catch (Exception e){
            return TResponseVo.error(500,e.getMessage());
        }
    }
}
